home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 48 / Amiga Format CD48 (1999-12-13)(Future Publishing)(GB)(Track 1 of 2)[!][issue 2000-01].iso / -in_the_mag- / networking / crosspc / parpc04 / packet / src / parnet.asm < prev    next >
Assembly Source File  |  1993-09-01  |  15KB  |  493 lines

  1. version    equ    1
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ; PARnet PC/FTP Packet Driver Source, conforming to version 1.08 of spec.
  6. ; Ported by S.A.Pechler (S.A.Pechler@bdk.tue.nl) from the Amiga's PARnet
  7. ; device. 
  8. ; Original Amiga code is Copyright (c) 1989 by Matthew Dillon.
  9. ; Date: July 10, 1993
  10.  
  11. ; Permission is granted to any individual or institution to use,copy,
  12. ; modify or redistribute this software provided this notice is retained.
  13. ; The authors make no guarantee to the suitability of the software for
  14. ; any purpose. Any damage caused by using this program is the responsibility
  15. ; of the user and not the authors. 
  16.  
  17. code    segment    word public
  18.     assume    cs:code, ds:code
  19.  
  20. ;    PARnet definitions
  21.  
  22. BUFSIZE        EQU 4096
  23. PARPORT         EQU 4          ; This is 1024 in 2 byte network order (0400h)
  24. TX_HDRSIZE      EQU 8
  25. ARP_TYPE    EQU 0608h      ; ARP packet type identifier in host order
  26.  
  27. ; Private Data
  28. ; ------------
  29. ; Driver definitions
  30.  
  31. ether_arp_frame    db 0,0,0,0,0
  32. arp_srcaddr    db ?        ; target ethernet address (myself)
  33.         db 0,0,0,0,0,0    ; source ethernet address (fake)
  34. ether_arp_type    db 8,6        ; type field (0806h)
  35.         db 0,1        ; hardware type (1 = ethernet)
  36.         db 8,0        ; protocol type ( 0800h = IP addresses)
  37.         db 6        ; hardware address length (6 for ethernet)
  38.         db 4        ; address length for high level (4 for IP addr)
  39.         db 0,2        ; operation: response
  40. arp_sendhard    db 0,0,0,0,0,?    ; sender hardware address
  41. arp_sendIP    db 0,0,0,0    ; sender IP address
  42. arp_targhard    db 0,0,0,0,0,?    ; target hardware address (myself)
  43. arp_targIP    db 0,0,0,0    ; target IP address (myself)
  44.  
  45. ether_arp_end label byte
  46.  
  47. ARP_LENGTH EQU ether_arp_end-ether_arp_frame
  48.  
  49. ; Receiver buffer (contains PARnet packet header)
  50. rx_buffer    db BUFSIZE dup(?)  ; receiver buffer (max 64 kb).
  51. rx_header    EQU rx_buffer
  52. rx_port        EQU rx_buffer    ; ! port number is in network order.
  53. rx_dlen        EQU rx_buffer+6 ; ! last 2 bytes of length (is in network
  54.                 ; ! order!).
  55. rx_data        EQU rx_buffer+8
  56.  
  57. ; pointer to receiver buffer (given to upper level process).
  58. ;rx_offset       dw rx_data              ; buffer data offset
  59.  
  60. ; transmitter packet header
  61. tx_header       dw PARport      ; portnumber is fixed to 1024 (in network order)
  62.         dw 0        ; checksum
  63.                 dw 0            ; length of datafield; it should be a DD
  64. tx_dlen         EQU this word
  65. tx_dlenh        db 0            ; but on PC's a PARnet packet can't be
  66. tx_dlenl        db 0            ; larger than 64 kb.
  67.  
  68. ; pointer to transmitter buffer
  69. tx_data        EQU this dword
  70. tx_offset    dw    ?    ; offset of host transmit buffer 
  71. tx_segment    dw    ?    ; segment of host transmit buffer 
  72. tx_length    dw    ?    ; packet length
  73.  
  74. tx_dest         db      ?       ; physical destination address
  75.  
  76. output_active   db      0       ; flag, packet being written.
  77.  
  78. ; Public Data
  79. ; -----------
  80.  
  81. public    int_no,io_addr,mem_base
  82.  
  83. int_no     db    2,0,0,0            ;must be four bytes long for get_number.
  84. io_addr dw    0378h,0            ;io addr for parallel card (default)
  85. mem_base dw    0,0            ;share memory addr (not used)
  86.  
  87. public    driver_class, driver_type, driver_name, driver_function, parameter_list
  88.  
  89. driver_class    db      1,0,0,0         ;no class specified for PARnet,
  90.                                         ;using class for serial line (the
  91.                     ;trailing zero's are for the
  92.                     ;print_number function
  93. driver_type     db      0,0,0,0         ;no specific type.
  94. driver_name    db    'PARnet',0    ;name of the driver.  
  95. driver_function    db    2        ;basic and extended functions present.
  96. parameter_list    label    byte
  97.     db    1        ;major rev of packet driver
  98.     db    9        ;minor rev of packet driver
  99.     db    14        ;length of parameter list
  100.     db    EADDR_LEN    ;length of MAC-layer address
  101.     dw    GIANT         ;MTU, including MAC headers
  102.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  103.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  104.     dw    0    ;(# of successive xmits) - 1
  105. int_num    dw    0    ;Interrupt # to hook for post-EOI
  106.             ;processing, 0 == none,
  107.  
  108.     public    rcv_modes
  109. rcv_modes       dw      7               ;number of receive modes in our table.
  110.                 dw      0,0,rcv_mode_2,0,0,0,rcv_mode_6
  111.  
  112. ; Private routines
  113. ; ----------------
  114.  
  115. ; See PARKERN.ASM
  116.  
  117. include parsubr.asm
  118.  
  119. ; Public routines
  120. ; ---------------
  121.  
  122.     public    as_send_pkt
  123. ; The Asynchronous Transmit Packet routine.
  124. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  125. ;   interrupts possibly enabled.
  126. ; Exit with nc if ok, or else cy if error, dh set to error number.
  127. ;   es:di and interrupt enable flag preserved on exit.
  128. as_send_pkt:
  129.     ret
  130.  
  131.     public    drop_pkt
  132. ; Drop a packet from the queue.
  133. ; Enter with es:di -> iocb.
  134. drop_pkt:
  135.     assume    ds:nothing
  136.     ret
  137.  
  138.     public    xmit
  139. ; Process a transmit interrupt with the least possible latency to achieve
  140. ;   back-to-back packet transmissions.
  141. ; May only use ax and dx.
  142. xmit:
  143.     assume    ds:nothing
  144.     ret
  145.  
  146.  
  147.     public    send_pkt
  148. send_pkt:
  149. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  150. ;  (only if the high-performance bit is set in driver_function)
  151. ;enter with ds:si -> packet, cx = packet length.
  152. ;exit with nc if ok, or else cy if error, dh set to error number.
  153.     assume    ds:nothing
  154.  
  155.     ;a PARnet network can't handle broadcasts, but ARP-requests will be
  156.     ;'answerred' by making an ARP-response with as hardware address the
  157.     ;LSB of the destination IP-address.
  158.  
  159.     mov    al,[si+EADDR_LEN-1]    ; get LSB of destination hard.address
  160.     cmp    al,-1            ; is it 0xff?
  161.     jne    send_pkt_nobrd        ; no, just send the packet
  162.     mov    ax,[si+EADDR_LEN+EADDR_LEN]    ; get packet type
  163.     cmp    ax,ARP_TYPE        ; is it an ARP-packet?
  164.     jne    send_pkt_err        ; no, can't handle this packet
  165.  
  166.     ; no need to save es:di here ?
  167.  
  168.     ; swap sender & targer address fields:
  169.  
  170.     ; 1. put sender addresses into target address fields
  171.     add    si,22        ; let SI point to sender's hardware address
  172.     mov    cx,EADDR_LEN+4    ; copy both the hardware & IP addresses
  173.     mov    ax,cs
  174.     mov    es,ax        ; mov es,cs ; is this needed?
  175.     mov    di,OFFSET arp_targhard
  176.     rep    movsb
  177.  
  178.     ; 2. put target IP address into sender IP address field
  179.     add    si,EADDR_LEN    ; skip target hardware address
  180.     mov    cx,4        ; IP address length
  181.     mov    di,OFFSET arp_sendIP
  182.     rep    movsb
  183.  
  184.     ; now calculate the target hardware address from the last octet of
  185.     ; the IP address.
  186.     mov    al,[si-1]
  187.     mov    arp_sendhard+5,al
  188.  
  189.     ; prepare arp response for the receiver
  190.  
  191.         mov     ax,cs                     ; ds=cs align
  192.         mov     ds,ax
  193.         assume  ds:code
  194.         mov     es,ax                     ; for es:di pointer
  195.         mov     di,offset ether_arp_type  ; pointer to type field
  196.         mov     si,offset ether_arp_frame ; pointer to start of frame
  197.         mov     cx,ARP_LENGTH             ; packet length
  198.         jmp     recv_reply_arp     ; Pass the arp response to the receiver
  199.  
  200. send_pkt_nobrd:
  201.     assume    ds:nothing
  202.  
  203.         mov     tx_segment,ds      ; tx->data
  204.  
  205.         mov     bx,cs              ; cs = ds align
  206.         mov     ds,bx
  207.  
  208.         assume  ds:code
  209.  
  210.         mov     tx_dest,al         ; hardware destination address.
  211.     mov    tx_offset,si       ; tx_offset ->segment offset 
  212.         mov     tx_length,cx       ; packet data length (host order)
  213.  
  214.  
  215.         ;Create a PARnet packet header
  216.     ;(At the moment it's simple: just fill in the data-length, the rest
  217.     ; is default)
  218.         mov     tx_dlenh,ch             ; put it in network order
  219.         mov     tx_dlenl,cl
  220.  
  221.     ;Send the packet
  222.         mov   output_active,1           ; set flag, to undo recv-interrupt
  223.         call  ParWrite                  ; see parsubr.asm
  224.         mov   output_active,0           ; recv-intrps are now accepted again
  225.         or    ax,ax                     ; check return value (# bytes written)
  226.         jz    send_pkt_err              ; = 0, can't..
  227.         js    send_pkt_err              ; < 0, error.
  228.         cmp   tx_length,ax              ; check if all bytes were written
  229.         jne   send_pkt_err              ; not, then error.
  230.         clc
  231.         jmp short send_pkt_end
  232. send_pkt_err:
  233.         mov dh,CANT_SEND                       ; errornum
  234.     stc
  235. send_pkt_end:
  236.     ret
  237.  
  238.  
  239.     public    get_address
  240.  
  241.  
  242. get_address:
  243. ;get the address of the interface.
  244. ;enter with es:di -> place to get the address, cx = size of address buffer.
  245. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  246.     assume    ds:code
  247.  
  248.     cmp    cx, EADDR_LEN        ; does caller want reasonable length?
  249.     jb    get_addr_fail        ; no , fails
  250.  
  251.     cld                ; make sure of string operation
  252.     mov    si,offset Par_EthAddr    ; load source of address
  253.     mov    cx,EADDR_LEN        ; return length of address
  254.     rep    movsb            ; copy address
  255.     mov    cx,EADDR_LEN        ; return length of address
  256.     clc
  257.     ret
  258. get_addr_fail:
  259.     stc
  260.     ret
  261.  
  262.     public    set_address
  263.  
  264. set_address:
  265. ;enter with ds:si -> Ethernet address, CX = length of address.
  266. ;exit with nc if okay, or cy, dh=error if any errors.
  267.     assume    ds:nothing
  268.  
  269.     cmp    cx,EADDR_LEN        ; check if address ok
  270.     je    set_addr_1    
  271.     mov    dh,BAD_ADDRESS        ; don't like length
  272.     stc
  273.     ret
  274. set_addr_1:
  275.     ; is ES always pointing to CS at this moment?
  276.     mov    di,offset Par_EthAddr    ;di->destination offset
  277.     rep    movsb            ;return address
  278.     mov    cx,EADDR_LEN        ;return their address length.
  279.     clc
  280.     ret
  281.  
  282. rcv_mode_2:
  283. ; Turn off receiver
  284.         ret
  285.  
  286. rcv_mode_6:
  287. ; Receive all packets (Promiscuous physical plus all multi)
  288.         ret
  289.  
  290.  
  291.     public    set_multicast_list
  292. set_multicast_list:
  293. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  294. ;return nc if we set all of them, or cy,dh=error if we didn't.
  295.     mov    dh,NO_MULTICAST
  296.     stc
  297.     ret
  298.  
  299.  
  300.     public    terminate
  301. terminate:
  302.     ret
  303.  
  304.     public    reset_interface
  305. reset_interface:
  306. ;reset the interface.
  307.     assume    ds:code
  308.  
  309.         call stable
  310.     ret
  311.  
  312. ;called when we want to determine what to do with a received packet.
  313. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  314.     extrn    recv_find: near
  315.  
  316. ;called after we have copied the packet into the buffer.
  317. ;enter with ds:si ->the packet, cx = length of the packet.
  318.     extrn    recv_copy: near
  319.  
  320.     extrn    count_in_err: near
  321.     extrn    count_out_err: near
  322.  
  323.     public    recv
  324. recv:
  325. ;called from the recv isr.  All registers have been saved, and ds=cs.
  326. ; all interrupts come here
  327. ;Upon exit, the interrupt will be acknowledged.
  328.     assume    ds:code
  329.     ;sti
  330.     cld
  331.  
  332.  
  333. ; an IRQ 7 occures only when an incoming packet is pending.
  334. ; so check with ParDataReady if the packet is addressed to me.
  335. ; otherwise quit.
  336. ; (is buffering needed?)
  337.  
  338. recv1:
  339.         cmp  output_active,1
  340.         je   Not_for_me         ; 1 = interrupt during write
  341.     call pardataready
  342.     or al,al
  343.     jz Line_idle        ; AL = 0, nothing on the line anymore
  344.     js Not_for_me        ; AL = -1, packet not addressed to me
  345.     
  346.     call parread
  347.         or ax,ax
  348.     jz Read_error        ; AL = 0, no bytes read
  349.     js Read_error        ; AL = -1, read timeout
  350.         cmp ax,BUFSIZE
  351.     jg Read_overflow    ; packet did not fit in buffer.
  352.  
  353. ; push packet to upper layer.
  354.  
  355.     mov    ch,rx_dlen        ; convert packet length
  356.     mov    cl,rx_dlen+1        ; to byte order.
  357.  
  358.         mov     ax,cs
  359.         mov     es,ax                   ; for es:di pointer in recv_find call
  360.         mov     di,offset rx_data       ; reset di to beginning
  361.     mov    si,di            ; si will be used later
  362.         add     di,EADDR_LEN+EADDR_LEN  ; point to type field
  363.                                         ; of buffer
  364.  
  365. recv_reply_arp:
  366.         mov     dl, BLUEBOOK            ;packet class: assume bluebook Ethernet
  367.  
  368.         push    cx                      ; save packet_length
  369.         push    si                      ; save packet start
  370.     call    recv_find        ; loop up our type (first call).
  371.         pop     si
  372.         pop     cx
  373.  
  374.     mov    ax,es            ; ax->es
  375.     or    ax,di            ; is this pointer null? (es=di=0)
  376.     je    rcv_no_copy
  377.  
  378.     push     cx            ; save packet length
  379.         push    es                      ; remember client's buffer
  380.     push    di
  381.  
  382.     rep    movsb            ; copy from SI (packet start) to
  383.                     ; DI (upper level buffer)
  384.         pop     si                      ; make client's buffer a new source
  385.         pop     ds                      ; for the recv_copy call.
  386.     pop    cx
  387.  
  388.     call    recv_copy        ; second call 
  389. rcv_no_copy:
  390. Line_Idle:
  391. Not_for_me:
  392. Read_error:
  393. Read_overflow:
  394.         mov   ax,cs               ; set DS back to CS, otherwise the
  395.         mov   ds,ax               ; remaining ISR routine will crash.
  396.         assume ds:code
  397.         ret
  398.  
  399.  
  400.     public    recv_exiting
  401. recv_exiting:
  402. ;called from the recv isr after interrupts have been acknowledged.
  403. ;Only ds and ax have been saved.
  404.     assume    ds:nothing
  405.     ret
  406.  
  407. ;any code after this will not be kept after initialization.
  408. end_resident    label    byte
  409.  
  410.     public    usage_msg
  411. usage_msg  db  "usage: PARNET [-n] [-d] [-w] <packet_int_no> <int_level> <io_addr> <netaddr>",CR,LF,'$'
  412.     public    copyright_msg
  413. copyright_msg   db    "Packet Driver for PARnet, version "
  414.                 db    '0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  415.                 db    "Ported by S.A.Pechler@bdk.tue.nl. "
  416.                 db    "Portions Copyright 1989, Matthew Dillon.",CR,LF,'$'
  417. int_no_name     db    "Interrupt number ",'$'
  418. io_addr_name    db    "I/O port ",'$'
  419. PARaddress_name db    "PARnet address ",'$'
  420. bad_addr_msg    db    "Bad PARnet address given.",CR,LF,'$'
  421.  
  422.     extrn    set_recv_isr: near
  423.  
  424. ;enter with si -> argument string, di -> word to store.
  425. ;if there is no number, don't change the number.
  426.     extrn    get_number: near
  427.  
  428. ;enter with dx -> name of word, di -> dword to print.
  429.     extrn    print_number: near
  430.  
  431.     extrn    error: near
  432.  
  433.     public    parse_args
  434. parse_args:
  435. ;exit with nc if all went well, cy otherwise.
  436.     mov    di,offset int_no
  437.     call     get_number
  438.     jc    param_error
  439.  
  440.  
  441.     mov    di,offset io_addr
  442.     call    get_number
  443.     jc    param_error
  444.  
  445.     mov    di,offset parnetaddr
  446.     call    get_number
  447.     jc    param_error
  448.  
  449. ;    call    print_parameters
  450.  
  451.         mov     al,parnetaddr
  452.         or      al,al      ; address 0 is reserved
  453.     je    parnet_err
  454.         cmp     al,-1      ; address 255 is reserved
  455.     je    parnet_err
  456.     mov    arp_srcaddr,al    ; initialize the arp response packet
  457.     clc
  458.     ret
  459.  
  460. param_error:
  461.     mov dx,offset usage_msg
  462.     jmp error
  463.  
  464. parnet_err:
  465.     mov dx,offset bad_addr_msg
  466.     jmp error    
  467.  
  468.     public    etopen
  469. etopen:
  470.     call    paraddress
  471.  
  472.     call    set_recv_isr        ;install the interrupt handler
  473.     mov    dx,offset end_resident
  474.     clc
  475.     ret
  476.  
  477.     public    print_parameters
  478. print_parameters:
  479.     mov    di,offset int_no
  480.     mov    dx,offset int_no_name
  481.     call     print_number
  482.     mov    di,offset io_addr
  483.     mov    dx,offset io_addr_name
  484.     call    print_number
  485.         mov     di,offset parnetaddr
  486.         mov     dx,offset PARaddress_name
  487.     call    print_number
  488.     ret
  489.  
  490. code    ends
  491.     end
  492.